package com.auerdi.utils;

import java.util.ArrayList;
import java.util.Stack;
import java.util.regex.Pattern;

/**
 * Created by cjf on 2018/1/11.
 */

public class CalculateUtils {
    //使用后缀 表达式来计算原表达式的值，得到double类型的结果。
    public static String calculate(String exp) throws Exception {
        exp = exp.replace("+", "+").replace("-", "-").replace("×", "*");
        ArrayList<String> inOrderExp = getStringList(exp);  //String转换为List,得到中缀表达式
        ArrayList<String> postOrderExp = getPostOrder(inOrderExp);
        long res = calPostOrderExp(postOrderExp);
        return String.valueOf(res);
    }

    //把数字和符号加入list
    private static ArrayList<String> getStringList(String s) {
        ArrayList<String> res = new ArrayList<String>();
        String num = "";
        for (int i = 0; i < s.length(); i++) {
            if (Character.isDigit(s.charAt(i))) {
                num += s.charAt(i);
            } else {
                if (Tool.isEffective(num)) {
                    res.add(num);//把上一个数字加到list
                }
                res.add(String.valueOf(s.charAt(i)));//把当前符号加到list
                num = "";
            }
        }
        //最后一个数字
        if (Tool.isEffective(num)) {
            res.add(num);
        }
        return res;
    }

    //将中缀表达式转化为后缀表达式
    private static ArrayList<String> getPostOrder(ArrayList<String> inOrderExp) {
        ArrayList<String> postOrderExp = new ArrayList<String>();//储存结果
        Stack<String> operStack = new Stack<String>();//运算符栈

        for (int i = 0; i < inOrderExp.size(); i++) {
            String cur = inOrderExp.get(i);
            if (isOper(cur)) {
                while (!operStack.isEmpty() && compareOper(operStack.peek(), cur)) {
                    //只要运算符栈不为空，并且栈顶符号优先级大与等于cur
                    postOrderExp.add(operStack.pop());
                }
                operStack.push(cur);
            } else {
                postOrderExp.add(cur);
            }
        }
        while (!operStack.isEmpty()) {
            postOrderExp.add(operStack.pop());
        }
        return postOrderExp;
    }

    //比较两个运算符的大小，如果peek优先级大于等于cur，返回true
    private static boolean compareOper(String peek, String cur) {
        if ("*".equals(peek) && ("*".equals(cur) || "+".equals(cur) || "-".equals(cur))) {
            return true;
        } else if ("+".equals(peek) && ("+".equals(cur) || "-".equals(cur))) {
            return true;
        } else if ("-".equals(peek) && ("+".equals(cur) || "-".equals(cur))) {
            return true;
        }
        return false;
    }

    //判断一个字符串是否是运算符，+-*/
    public static boolean isOper(String c) {
        if (c.equals("+") ||
                c.equals("-") ||
                c.equals("*") ||
                c.equals("×"))return true;
        return false;
    }


    //计算一个后缀表达式
    private static Long calPostOrderExp(ArrayList<String> postOrderExp) throws Exception {
        Stack<String> stack = new Stack<String>();
        for (int i = 0; i < postOrderExp.size(); i++) {
            String curString = postOrderExp.get(i);
            if (isOper(curString)) {
                long a = Long.valueOf(stack.pop());
                long b = Long.valueOf(stack.pop());
                long res = 0;
                switch (curString.charAt(0)) {
                    case '+':
                        res = b + a;
                        break;
                    case '-':
                        res = b - a;
                        break;
                    case '*':
                        res = b * a;
                        break;
                }
                stack.push(String.valueOf(res));
            } else {
                stack.push(curString);
            }
        }
        return Long.valueOf(stack.pop());
    }
    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }
}
